home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / thesrc10.zip / THE.C < prev    next >
C/C++ Source or Header  |  1992-08-12  |  20KB  |  533 lines

  1. /***********************************************************************/
  2. /* THE.C - The Hessling Editor                                         */
  3. /***********************************************************************/
  4. /*
  5.  * THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
  6.  * Copyright (C) 1991,1992 Mark Hessling
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as
  10.  * published by the Free Software Foundation; either version 2 of
  11.  * the License, or any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to:
  20.  *
  21.  *    The Free Software Foundation, Inc.
  22.  *    675 Mass Ave,
  23.  *    Cambridge, MA 02139 USA.
  24.  *
  25.  *
  26.  * If you make modifications to this software that you feel increases
  27.  * it usefulness for the rest of the community, please email the
  28.  * changes, enhancements, bug fixes as well as any and all ideas to me.
  29.  * This software is going to be maintained and enhanced as deemed
  30.  * necessary by the community.
  31.  *
  32.  * Mark Hessling                     email: M.Hessling@itc.gu.edu.au
  33.  * 36 David Road                     Phone: +61 7 849 7731
  34.  * Holland Park                      Fax:   +61 7 875 7877
  35.  * QLD 4121
  36.  * Australia
  37.  */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <signal.h>
  41. #define MAIN 1
  42. #include "the.h"
  43.  
  44. /*#define DEBUG 1*/
  45.  
  46. /*--------------------------- global data -----------------------------*/
  47.  WINDOW *foot,*error_window,*divider;
  48.  VIEW_DETAILS *vd_current=(VIEW_DETAILS *)NULL;
  49.  VIEW_DETAILS *vd_first=(VIEW_DETAILS *)NULL;
  50.  VIEW_DETAILS *vd_mark=(VIEW_DETAILS *)NULL;
  51.  char number_of_views = 0;                          /* number of views */
  52.  char number_of_files = 0;                          /* number of files */
  53.  char display_screens = 1;                        /* number of screens */
  54.  char current_screen = 0;
  55.  SCREEN_DETAILS screen[MAX_SCREENS];            /* 2 screen structures */
  56.  bool horizontal=TRUE;
  57.  short save_coord_x[VIEW_WINDOWS];
  58.  short save_coord_y[VIEW_WINDOWS];
  59.  
  60.  LINE *next_line,*curr_line;
  61.  LINE *first_profile_command=NULL,*current_profile_command=NULL;
  62.  LINE *first_file_name=NULL,*current_file_name=NULL;
  63.  char error_on_screen;
  64.  unsigned char *rec;
  65.  unsigned short rec_len = 0;                          /* length of rec */
  66.  unsigned char *cmd_rec;
  67.  unsigned short cmd_rec_len = 0;                  /* length of cmd_rec */
  68.  unsigned char focus_changed = NO;   /* indicates if focus line has changed */
  69.  unsigned char current_changed = NO; /* indicates if current line has changed */
  70.  unsigned char mode_insert=YES;          /* defines insert mode toggle */
  71.  unsigned char in_profile;          /* indicates if processing profile */
  72.  unsigned char file_read=NO;     /* indicates if we have read the file */
  73.  
  74.  unsigned char *profilename = (unsigned char *)"PROFILE.THE";
  75.  unsigned char *helpfilename = (unsigned char *)"THE.HLP";
  76.  unsigned char *tempfilename = (unsigned char *)"THE.$$$";
  77. #ifdef VMS
  78.  unsigned char *dirfilename = (unsigned char *)"DIR.THE";
  79. #else
  80.  unsigned char *dirfilename = (unsigned char *)"DIR.DIR";
  81. #endif
  82.  unsigned char help_pathname[MAX_FILE_NAME+1];
  83.  unsigned char profile_pathname[MAX_FILE_NAME+1];
  84.  unsigned char dir_pathname[MAX_FILE_NAME+1];
  85.  unsigned char dir_filename[MAX_FILE_NAME+1];
  86.  unsigned char curr_path[MAX_FILE_NAME+1];
  87.  unsigned char sp_path[MAX_FILE_NAME+1];
  88.  unsigned char sp_fname[MAX_FILE_NAME+1];
  89.  unsigned char dir_path[MAX_FILE_NAME+1];   /* for dir and ls commands */
  90.  
  91.  unsigned short file_start = 36;
  92.  unsigned char *last_target;
  93.  
  94. #ifdef UNIX
  95.  unsigned char *spooler_name;
  96. #endif
  97.  
  98. char file_disposition;
  99.  
  100. struct stat stat_buf;
  101.  
  102. /*---------------------------------------------------------------------*/
  103. /* Following are for getopt function(s).                               */
  104. /*---------------------------------------------------------------------*/
  105. extern char *optarg;
  106. extern int optind;
  107.  
  108. /*---------------------- function definitions -------------------------*/
  109. void handle_signal();
  110. void init_signals();
  111. void set_default_colours();
  112. void display_info();
  113. int Edit();
  114. /***********************************************************************/
  115. #ifdef PROTO
  116. int main(int argc, unsigned char *argv[])
  117. #else
  118. int main(argc,argv)
  119. int argc;
  120. unsigned char *argv[];
  121. #endif
  122. /***********************************************************************/
  123. {
  124. /*-------------------------- external data ----------------------------*/
  125.  
  126. /*---------------------- function definitions -------------------------*/
  127.  
  128. /*--------------------------- local data ------------------------------*/
  129.  register int i,j,k;
  130.  unsigned char *prf;
  131.  char c;
  132.  int malloc_fd;
  133.  bool trap_signals=TRUE;
  134. /*--------------------------- processing ------------------------------*/
  135. #ifdef TRACE
  136.  trace_initialise();
  137.  trace_function("the.c:     main");
  138. #endif
  139. /*---------------------------------------------------------------------*/
  140. /* Set up flag to indicate that we are not interactive...yet.          */
  141. /*---------------------------------------------------------------------*/
  142.  in_profile = YES;
  143. /*---------------------------------------------------------------------*/
  144. /* Call insertmode command to set default mode to overwrite. Main      */
  145. /* reason for this is for the DOS version to set the shape of the      */
  146. /* cursor.                                                             */
  147. /*---------------------------------------------------------------------*/
  148.  Insertmode((unsigned char *)"");
  149. /*---------------------------------------------------------------------*/
  150. /* Initialise the printer spooler.                                     */
  151. /*---------------------------------------------------------------------*/
  152. #ifdef UNIX
  153.  if ((spooler_name = (unsigned char *)memMalloc(4,"spooler")) == NULL)
  154.    {
  155.     display_error(30,"");
  156.     exit_clean(1);
  157.    }
  158.  strcpy(spooler_name,"lpr");
  159. #endif
  160. /*---------------------------------------------------------------------*/
  161. /* Set up memory for profile file name.                                */
  162. /*---------------------------------------------------------------------*/
  163.  if ((prf = (unsigned char *)memMalloc(80,"prf *")) == NULL)
  164.    {
  165.     display_error(30,"");
  166.     exit_clean(1);
  167.    }
  168.  strcpy(prf,"");
  169.  while ((c = getopt(argc,argv,"sp:w:h?")) != (-1))
  170.    switch(c)
  171.      {
  172.       case 's':        /* don't trap signals */
  173.                trap_signals = FALSE;
  174.                break;
  175.       case 'p':        /* profile file name */
  176.                strcpy(prf,optarg);
  177.                break;
  178.       case 'w':        /* width of line */
  179.                MAX_LINE_LENGTH = (short)atoi(optarg);
  180.                if (MAX_LINE_LENGTH < 10)
  181.                  {
  182.                   display_error(5,"width MUST be >= 10");
  183.                   exit_clean(1);
  184.                  }
  185.                break;
  186.       case 'h':
  187.       case '?':
  188.                display_info();
  189.                exit_clean(0);
  190.                break;
  191.       default:
  192.                break;
  193.      }
  194.  
  195.  if (optind<argc)
  196.    {
  197.     while(optind<argc)
  198.       {
  199.        if ((current_file_name = add_line(first_file_name,
  200.                                          current_file_name,
  201.                                          argv[optind],
  202.                                          strlen(argv[optind]))) == NULL)
  203.            {
  204.             display_error(30,"");
  205.             exit_clean(1);
  206.            }
  207.        if (first_file_name == NULL)
  208.           first_file_name = current_file_name;
  209.        optind++;
  210.       }
  211.    }
  212.  else
  213.    {
  214.     if ((current_file_name = add_line(first_file_name,
  215.                                       current_file_name,
  216.                                       CURRENT_DIR,
  217.                                       strlen(CURRENT_DIR))) == NULL)
  218.         {
  219.          display_error(30,"");
  220.          exit_clean(1);
  221.         }
  222.     if (first_file_name == NULL)
  223.        first_file_name = current_file_name;
  224.    }
  225.  mark_end_col=MAX_LINE_LENGTH-1;
  226.  
  227. /*---------------------------------------------------------------------*/
  228. /* Allocate some memory to last_target and set it to a blank value.    */
  229. /*---------------------------------------------------------------------*/
  230.  if ((last_target = (unsigned char *)memMalloc(80,"last target")) == NULL)
  231.     exit_clean(1);
  232.  strcpy(last_target,"");
  233.  
  234. /*---------------------------------------------------------------------*/
  235. /* Allocate some memory to rec.                                        */
  236. /*---------------------------------------------------------------------*/
  237.  if ((rec = (unsigned char *)memMalloc(MAX_LINE_LENGTH,"rec")) == NULL)
  238.     exit_clean(1);
  239.  
  240. /*---------------------------------------------------------------------*/
  241. /* Determine the current working directory.                            */
  242. /* Do this before any other file setting up so that we don't change the*/
  243. /* current directory from the default.                                 */
  244. /*---------------------------------------------------------------------*/
  245. #ifdef MALLOC_DEBUG
  246.  malloc_fd = open("malloc.dump",O_RDWR);
  247.  malloc_dump(malloc_fd);
  248.  malloc_chain_check(1);
  249.  close(malloc_fd);
  250.  fprintf(stderr,"Just before getcwd()\n");
  251. #endif
  252.  getcwd(curr_path,MAX_FILE_NAME);
  253.  
  254. /*---------------------------------------------------------------------*/
  255. /* Determine calling path for help and profile files.                  */
  256. /*---------------------------------------------------------------------*/
  257.  strcpy(profile_pathname,argv[0]);
  258.  i = strzreveq(profile_pathname,SLASH);
  259.  if (i != (-1))
  260.     profile_pathname[i+1] = '\0';
  261.  strcpy(help_pathname,profile_pathname);
  262.  strcat(help_pathname,helpfilename);
  263.  strcat(profile_pathname,profilename);
  264.  
  265. /*---------------------------------------------------------------------*/
  266. /* Set up filename for directory temporary file (DIR.DIR)              */
  267. /*---------------------------------------------------------------------*/
  268. #ifdef UNIX
  269.  strcpy(dir_pathname,getenv("HOME"));
  270. #endif
  271. #if defined(DOS) || defined(OS2)
  272.  strcpy(dir_pathname,"\\");
  273. #endif
  274. #ifdef VMS
  275.  strcpy(dir_pathname,"");
  276. #endif
  277.  
  278.  if (strlen(dir_pathname) > 0)
  279.     if (*(dir_pathname+strlen(dir_pathname)-1) != SLASH)
  280.        strcat(dir_pathname,STR_SLASH);
  281.  strcat(dir_pathname,dirfilename);
  282.  if (splitpath(dir_pathname) == ERROR)
  283.     exit_clean(1);
  284.  strcpy(dir_pathname,sp_path);
  285.  strcpy(dir_filename,sp_fname);
  286.  
  287. /*---------------------------------------------------------------------*/
  288. /* Set up default values for SET commands etc.                         */
  289. /*---------------------------------------------------------------------*/
  290.  set_defaults();
  291.  set_screen_defaults();
  292. /*---------------------------------------------------------------------*/
  293. /* Set up initial colours to 0.                                        */
  294. /*---------------------------------------------------------------------*/
  295.  for (i=0;i<ATTR_MAX;i++)
  296.      colour[i] = (chtype)0;
  297. /*---------------------------------------------------------------------*/
  298. /* Initialise command array to empty strings.                          */
  299. /*---------------------------------------------------------------------*/
  300.  init_command();
  301. /*---------------------------------------------------------------------*/
  302. /* Read the profile file and execute any 'set' commands that must be   */
  303. /* executed BEFORE we read the file to edit. If the commands in the    */
  304. /* profile file are to be executed against the file to edit, save the  */
  305. /* commands in a linked list to be executed after we read the file.    */
  306. /*---------------------------------------------------------------------*/
  307.  
  308.  if (get_profile(prf) == QUIT)
  309.      exit_clean(0);
  310.  
  311.  if (get_file(first_file_name->line) == ERROR)
  312.      exit_clean(1);
  313.  
  314.  CURRENT_VIEW->current_window = WINDOW_COMMAND;
  315.  file_read = YES;
  316.  /* process any post file commands */
  317. /*---------------------------------------------------------------------*/
  318. /* Set rec to point to the first line ie. Top of File                  */
  319. /*---------------------------------------------------------------------*/
  320.  memset(rec,' ',MAX_LINE_LENGTH);
  321.  rec_len = strlen(TOP_OF_FILE);
  322.  memcpy(rec,TOP_OF_FILE,rec_len);
  323.  
  324.  current_profile_command = first_profile_command;
  325.  while(current_profile_command != NULL)
  326.    {
  327.     if (command_line(current_profile_command->line) != OK)
  328.        exit_clean(1);
  329.     current_profile_command = current_profile_command->next;
  330.    }
  331.  ll_free(first_profile_command);
  332. /*---------------------------------------------------------------------*/
  333. /* Start up curses. This allows profile commands to be processed before*/
  334. /* curses starts.                                                      */
  335. /*---------------------------------------------------------------------*/
  336.  if (trap_signals)
  337.     init_signals();
  338.  initscr();
  339. #ifdef COLOR_CURSES
  340.  if (has_colors() == TRUE)
  341.     start_color();
  342. #endif
  343. #ifndef VMS
  344.  cbreak();
  345. #endif
  346. #ifndef MINIX
  347.  raw();
  348. #endif
  349. #if defined(DOS) || defined(OS2)
  350.  raw_output(TRUE);
  351. #endif
  352.  nonl();
  353.  noecho();
  354. #if !defined(SUN) && !defined(VMS)
  355.  keypad(stdscr,TRUE);
  356. #endif
  357.  in_profile = NO;
  358. /*---------------------------------------------------------------------*/
  359. /* Allocate memory to cmd_rec and set it to blanks.                    */
  360. /* This is done here so that COLS is valid; set up by initscr().       */
  361. /*---------------------------------------------------------------------*/
  362.  if ((cmd_rec = (unsigned char *)memMalloc(COLS,"cmd_rec")) == NULL)
  363.     exit_clean(1);
  364.  memset(cmd_rec,' ',COLS);
  365.  cmd_rec_len = 0;
  366. /*---------------------------------------------------------------------*/
  367. /* Set up default colours for each window component.                   */
  368. /*---------------------------------------------------------------------*/
  369.  set_screen_defaults();
  370.  set_default_colours();
  371. /*---------------------------------------------------------------------*/
  372. /* Set up all windows for the first file.                              */
  373. /* This also sets up 'colours' for monochrome terminals and screens.   */
  374. /*---------------------------------------------------------------------*/
  375.  set_up_windows();
  376.  
  377.  foot = newwin(1,COLS,LINES-1,0);
  378.  error_window = newwin(1,COLS,LINES-1,0);
  379.  divider = newwin(LINES-1,2,0,(COLS/2)-1);
  380.  wattrset(foot,colour[ATTR_STATAREA]);
  381.  wattrset(error_window,colour[ATTR_MSGLINE]);
  382.  wattrset(divider,colour[ATTR_DIVIDER]);
  383.  
  384.  for (i=0;i<COLS;i++)
  385.       mvwaddch(foot,0,i,' ');
  386.  wmove(foot,0,0);
  387.  waddstr(foot,"THE 1.0");
  388.  wmove(divider,0,0);
  389.  for (i=0;i<LINES-1;i++)
  390.       mvwaddstr(divider,i,0,"||");
  391. /*---------------------------------------------------------------------*/
  392. /* Edit any other files input on the command line.                     */
  393. /*---------------------------------------------------------------------*/
  394.  current_file_name = first_file_name->next;
  395.  while(current_file_name != NULL)
  396.    {
  397.     if (Edit(current_file_name->line) == ERROR)
  398.        exit_clean(1);
  399.     current_file_name = current_file_name->next;
  400.    }
  401.  ll_free(first_file_name);
  402.  CURRENT_VIEW = CURRENT_SCREEN.screen_view = vd_first;
  403.  pre_process_line(CURRENT_VIEW->focus_line);
  404. /*---------------------------------------------------------------------*/
  405. /* This is where it all happens.                                       */
  406. /*---------------------------------------------------------------------*/
  407.  editor();
  408.  
  409.  strcpy(sp_path,dir_pathname);
  410.  strcat(sp_path,dir_filename);
  411.  remove_file(sp_path);
  412. /*---------------------------------------------------------------------*/
  413. /* Free up the dynamically allocated memory.                           */
  414. /*---------------------------------------------------------------------*/
  415.  free_define_memory();
  416.  memFree(last_target,"last target");
  417.  memFree(rec,"rec");
  418.  memFree(cmd_rec,"cmd_rec");
  419.  memFree(prf,"prf");
  420.  add_to_recovery_list(NULL,(-1));      /* frees up memory for recovery */
  421.  
  422.  wmove(foot,0,4);
  423.  waddstr(foot,"- END");
  424.  wrefresh(foot);
  425.  
  426. #ifdef UNIX
  427.  memFree(spooler_name,"spooler");
  428. #endif
  429.  
  430.  delwin(divider);
  431.  delwin(error_window);
  432.  delwin(foot);
  433.  endwin();
  434.  exit_clean(0);
  435. }
  436. /***********************************************************************/
  437. #ifdef PROTO
  438. void init_signals(void)
  439. #else
  440. void init_signals()
  441. #endif
  442. /***********************************************************************/
  443. {
  444. /*--------------------------- local data ------------------------------*/
  445. /*--------------------------- processing ------------------------------*/
  446. #ifdef TRACE
  447.  trace_function("the.c:     init_signals");
  448. #endif
  449. #ifdef UNIX
  450.  signal(SIGQUIT,handle_signal);
  451.  signal(SIGHUP,handle_signal);
  452.  signal(SIGBUS,handle_signal);
  453.  signal(SIGABRT,handle_signal);
  454.  signal(SIGFPE,handle_signal);
  455.  signal(SIGSEGV,handle_signal);
  456.  signal(SIGINT,handle_signal);
  457.  signal(SIGTERM,handle_signal);
  458. #endif
  459. #ifdef TRACE
  460.  trace_return();
  461. #endif
  462.  return;
  463. }
  464. #ifdef UNIX
  465. /***********************************************************************/
  466. #ifdef PROTO
  467. void handle_signal(int errno)
  468. #else
  469. void handle_signal(errno)
  470. int errno;
  471. #endif
  472. /***********************************************************************/
  473. {
  474. /*--------------------------- local data ------------------------------*/
  475. /*--------------------------- processing ------------------------------*/
  476. #ifdef TRACE
  477.  trace_function("the.c:     handle_signal");
  478. #endif
  479.  endwin();
  480.  fprintf(stderr,"\nTHE terminated with signal: %d\n\n",errno);
  481.  exit_clean(2);
  482. }
  483. #endif
  484. /***********************************************************************/
  485. #ifdef PROTO
  486. void display_info(void)
  487. #else
  488. void display_info()
  489. #endif
  490. /***********************************************************************/
  491. {
  492. /*--------------------------- local data ------------------------------*/
  493. /*--------------------------- processing ------------------------------*/
  494.  
  495.  fprintf(stderr,"\nTHE 1.0 Copyright (C) 1991,1992 Mark Hessling\n");
  496.  fprintf(stderr,"All rights reserved.\n");
  497.  fprintf(stderr,"THE is distributed under the terms of the GNU\n");
  498.  fprintf(stderr,"General Public License and comes with NO WARRANTY.\n");
  499.  fprintf(stderr,"See the file COPYING for details.\n");
  500.  fprintf(stderr,"\nUsage: THE [-s] [-p profile] [-w width] [filename [...] | dir [...]]\n\n");
  501.  fflush(stderr);
  502.  return;
  503. }
  504. /***********************************************************************/
  505. #ifdef PROTO
  506. void exit_clean(short err_num)
  507. #else
  508. void exit_clean(err_num)
  509. short err_num;
  510. #endif
  511. /***********************************************************************/
  512. {
  513. /*--------------------------- local data ------------------------------*/
  514. #ifdef DOS
  515. char get_mode(void);
  516. #endif
  517. /*--------------------------- processing ------------------------------*/
  518. #ifdef TRACE
  519.  trace_function("the.c:     exit_clean");
  520. #endif
  521. #if defined(DOS) || defined(OS2)
  522.  mode_insert=NO;
  523.  draw_cursor();
  524. #endif
  525.  
  526.  if (file_exists(tempfilename))
  527.     remove_file(tempfilename);
  528. #ifdef TRACE
  529.  trace_return();
  530. #endif
  531.  exit(err_num);
  532. }
  533.